#pragma once

#include "SafeQueue.hpp"
#include "QuitableThread.hpp"
#include "LogItem.hpp"
#include "Packet.hpp"

#include <vector>

namespace cybertron{
	class MsgEncoder : public QuitableThread
	{
	public:
		MsgEncoder(SafeQueue<LogItem> *input_queue, SafeQueue<NetPacket> *output_queue)
			: _input_queue(input_queue)
			, _output_queue(output_queue) {};

		virtual ~MsgEncoder() {};

	private:
		virtual void run_once() {
			LogItem *item = _input_queue->dequeue();
			if (!item) {
				return;
			}

			std::string s = item->to_net_message();
			NetPacket *p = new NetPacket();
			p->set_data(s.c_str(), s.length());
			if (!_output_queue->enqueue(p)) {
				delete p;
			}
			delete item;
		};
		SafeQueue<LogItem> *_input_queue;
		SafeQueue<NetPacket> *_output_queue;
	};

	class MsgDecoder : public QuitableThread
	{
	public:
		MsgDecoder(SafeQueue<NetPacket> *input_queue, std::vector<SafeQueue<LogItem> *> *output_queues)
			: _input_queue(input_queue)
			, _output_queues(output_queues) {};
		virtual ~MsgDecoder() {};

		virtual void run_once() {
			NetPacket *packet = _input_queue->dequeue();
			if (!packet) {
				return;
			}

			std::string message = std::string((const char *)packet->body(), packet->body_len());
			LogItem *item = LogItemBuilder::build_item_from_net_message(message);
			if (item) {
				//if (item->from_net_message(message) != 0 || !_output_queue->enqueue(item, 500)) {
				//	delete item;
				//}
				if (item->from_net_message(message) != 0) {
					delete item;
				}
				else {
					SafeQueue<LogItem> *output_queue = _output_queues->at(item->category_id() % _output_queues->size());
					if (!output_queue->enqueue(item)) {
						delete item;
					}
				}
			}
			delete packet;
		};
	private:
		SafeQueue<NetPacket> *_input_queue;
		std::vector<SafeQueue<LogItem> *> *_output_queues;
	};
}
